<template>
  <div class="table_page">
    <slot name="tableHeader">
      <table-header
        v-if="showHeader"
        ref="headerRef"
        :buttonList="buttonList"
        :size="size"
        :title="title"
        :showSearch="showSearch"
        :showExport="showExport"
        :showDataExport="showDataExport"
        :searchPlaceholder="searchPlaceholder"
        :tableList="tableList"
        :exportInfo="exportInfo"
        :actionStyle="actionStyle"
        :showChangeHeader="showChangeHeader"
        :exportTitle="exportTitle"
        :showPagination="showPagination"
        v-bind="{ ...searchFormConfig }"
        @buttonClick="data => emits('buttonClick', data)"
        @resetPageNum="searchChange"
        @columnChange="columnChange"
      >
        <template #headerTitle>
          <slot name="headerTitle"></slot>
        </template>
        <template #titleTip>
          <slot name="titleTip"></slot>
        </template>
        <template #searchBefore>
          <slot name="searchBefore"></slot>
        </template>
        <template #searchAfter>
          <slot name="searchAfter"></slot>
        </template>
      </table-header>
    </slot>
    <div class="table_box" :style="{ maxHeight: maxHeight, ...tableConfig.style }">
      <op-table
        ref="tableRef"
        :loading="tableLoading"
        :show-summary="showSummary"
        :summary-method="
          e => handleSummaryMethod({ e, countNumMap: countNumMap, unit: summaryUnit })
        "
        :tableData="tableData"
        :tableList="tableShowList"
        :tableConfig="{ ...tableConfig, height: '100%' }"
        @tableEvent="data => emits('tableEvent', data)"
        @cellDblclick="cellDblclick"
        @handleSelectionChange="handleSelectionChange"
        @handleCurrentRowChange="handleCurrentRowChange"
        @handleCellContextmenu="handleCellContextmenu"
        @handleHeaderContextmenu="handleHeaderContextmenu"
        @handleSelect="handleSelect"
        @handleSelectAll="handleSelectAll"
        @handleSingleSelect="handleSingleSelect"
        @rowClick="rowClick"
      >
        <template #prepend>
          <slot name="prepend" />
        </template>
        <template #column="{ scope, column }">
          <slot :name="column.slot" :scope="scope" :column="column"></slot>
        </template>
        <template #headerColumn="{ scope, column }">
          <slot :name="column.headerProp" :scope="scope" :column="column"></slot>
        </template>
        <template #append>
          <slot name="prepend" />
        </template>
      </op-table>
    </div>
    <op-pagination
      ref="paginationRef"
      class="table_page_pagination"
      v-if="showPagination"
      v-bind="paginationProps"
      :total="total"
      @handlePageChange="getDataList"
    ></op-pagination>
  </div>
</template>
<script setup>
import { ElMessage } from 'element-plus';
import { apiMethods } from '@/utils/http.js';
import { handleSummaryMethod } from '@/utils/index.js';
import _ from 'lodash';
import TableHeader from './components/TableHeader.vue';

const props = defineProps({
  size: {
    type: String,
    default: 'small',
  },
  title: {
    type: String,
    default: '',
  },
  showHeader: {
    // 是否展示头部
    type: Boolean,
    default: true,
  },
  showSearch: {
    type: Boolean,
    default: true,
  },
  showExport: {
    type: Boolean,
    default: true,
  },
  showDataExport: {
    type: Boolean,
    default: false,
  },
  searchPlaceholder: {
    type: String,
    default: 'Search',
  },
  buttonList: {
    // 头部的按钮配置
    type: Array,
    default: () => [],
  },
  tableList: {
    type: Array,
    default: () => [],
  },
  tableConfig: {
    type: Object,
    default: () => ({}),
  },
  showSummary: {
    type: Boolean,
    default: false,
  },
  showPagination: {
    // 是否展示分页
    type: Boolean,
    default: true,
  },
  paginationProps: {
    // 分页配置
    type: Object,
    default: () => ({}),
  },
  searchFormConfig: {
    // 查询条件status，project和date配置
    type: Object,
    default: () => ({}),
  },
  axiosMethod: {
    type: String,
    default: 'post',
  },
  requestApi: {
    // 列表接口
    type: String,
    default: '',
  },
  exportConfig: {
    // 列表配置
    type: Object,
    default: () => ({}),
  },
  requestParams: {
    // 默认值
    type: Object,
    default: () => ({}),
  },
  summaryUnit: {
    // table 统计是否携带单位
    type: Object,
    default: () => ({}),
  },
  actionStyle: {
    type: [String, Object],
  },
  isClearSelection: {
    // table 查询时，是否清除已选选项
    type: Boolean,
    default: true,
  },
  currentRowNum: {
    // 初始化，默认选中第几行
    type: Number,
    default: 0,
  },
  tierData: {
    // 调用接口获取数据的层级关系
    type: String,
    default: '',
  },
  showChangeHeader: {
    // 是否展示自定义设置表头
    type: Boolean,
    default: true,
  },
  exportTitle: {
    // 导出图片后面文字
    type: String,
    default: '',
  },
});

const headerRef = ref();
const paginationRef = ref();
const tableRef = ref();

const emits = defineEmits([
  'buttonClick',
  'getTableDataList',
  'tableEvent',
  'cellDblclick',
  'handleSelectionChange',
  'handleCurrentRowChange',
  'handleCellContextmenu',
  'handleHeaderContextmenu',
  'handleSingleSelect',
  'handleSelect',
  'handleSelectAll',
  'callback',
  'rowClick',
  'searchChange',
]);

const searchParams = ref({});
const tableData = ref([]);
const total = ref(0);
const tableShowList = ref(props.tableList);
const tableLoading = ref(false);
const countNumMap = ref({});
const maxHeight = ref('');

// 导出
const exportInfo = computed(() => {
  return {
    search: searchParams.value,
    ...props.exportConfig,
  };
});

onMounted(() => {
  nextTick(() => {
    tableHeightDebounce();
  });
  window.addEventListener('resize', tableHeightDebounce);
});

onUnmounted(() => {
  window.removeEventListener('resize', tableHeightDebounce);
});

// 查询条件改变
function searchChange(num, data) {
  emits('searchChange', data);
  resetPageNum(num);
}

// 重置pageNum & 重新获取tableData
function resetPageNum(num) {
  if (props.showPagination && num) {
    paginationRef.value.currentNum = 1 || num;
  }
  getDataList();
}

// 查询列表接口
async function getDataList() {
  let obj = {
    ...props.requestParams,
  };
  if (props.showHeader) obj = { ...obj, ...headerRef.value.searchParams };
  if (props.showPagination) {
    obj.pageSize = paginationRef.value.currentSize;
    obj.pageNum = paginationRef.value.currentNum;
  }
  searchParams.value = obj;
  if (!props.requestApi) {
    emits('getTableDataList', obj);
    return;
  }
  tableLoading.value = true;
  apiMethods[props.axiosMethod](props.requestApi, {
    ...searchParams.value,
  })
    .then(res => {
      tableLoading.value = false;
      let data = res.data;
      let code = data.code || data.errorCode;
      if (code === '200') {
        setTableInfo(data.data);
        emits('callback', { res: data.data });
        // 重新调接口，清除选中项
        if (props.isClearSelection) {
          handleSelect([], {});
          handleSelectAll([]);
          handleSingleSelect({});
        }
        // 默认选中第几行
        if (props.currentRowNum && tableData.value?.length) {
          nextTick(() => {
            let [row] = tableData.value.slice(props.currentRowNum - 1, props.currentRowNum);
            tableRef.value.setCurrentRow(row);
          });
        }
      } else {
        ElMessage.error(data.msg || 'Failed');
      }
    })
    .catch(err => {
      tableLoading.value = false;
      ElMessage.error(err.msg || 'Failed');
    });
}

// 设置tabledata和total
function setTableInfo(res) {
  // 获取table数据，处理后端返回数据通用or特殊的层级关系
  let arr = null;
  if (props.tierData) {
    let tierArr = props.tierData.split('.');
    tierArr.forEach(item => {
      arr = arr ? arr[item] : res[item];
    });
  } else {
    arr = props.showPagination ? res?.content || [] : res || [];
  }
  tableData.value = arr;
  if (props.showPagination) total.value = res?.totalSize ? Number(res.totalSize) : 0;
  if (props.showSummary) countNumMap.value = res?.countNumMap || null;
}

// 列字段展示
function columnChange(checkedList) {
  const arr = _.cloneDeep(props.tableList);
  let filterArr = recurison(arr, checkedList);
  if (checkedList.length === 0) {
    filterArr = filterArr.filter(i => {
      return i.label !== 'Action';
    });
  }
  tableShowList.value = filterArr;
  nextTick(() => {
    tableRef.value.initTable();
  });
}
function recurison(arr, checkedList, father) {
  return arr.filter(item => {
    if (item.children) {
      const childArr = recurison(item.children, checkedList, item);
      Object.assign(item, { children: [...childArr] });
      return childArr.length;
    } else if (father) {
      for (let i = 0; i < checkedList.length; i++) {
        const checkedItem = checkedList[i];
        // 比较checkedItem.label与item.label，再拆分id匹配father
        let cLable = checkedItem.labelDiff || checkedItem.label;
        let iLabel = item.labelDiff || item.label;
        if (cLable === iLabel) {
          if (checkedItem.id?.split(father?.labelDiff || father?.label)?.length != 1) {
            return true;
          }
        }
      }
    } else {
      let iLabel = item.labelDiff || item.label;
      return (
        checkedList.map(i => i.labelDiff || i.label).includes(iLabel) ||
        item.type ||
        item.label === 'Action'
      );
    }
  });
}

// 设置table高度防抖
function tableHeightDebounce() {
  let timer;
  if (timer) {
    clearTimeout(timer);
  }
  timer = setTimeout(() => {
    setTableMaxHeight();
  }, 200);
}
// 设置table高度
function setTableMaxHeight() {
  let headerHeight = 0;
  let paginationHeight = 0;
  if (props.showHeader) {
    let heightFlag = document.querySelector('.table_header')?.clientHeight;
    headerHeight = heightFlag || 32;
  }
  if (props.showPagination) paginationHeight = 32;
  maxHeight.value = `calc(100% - ${headerHeight}px - ${paginationHeight}px)`;
}

// table事件
function initTable() {
  tableShowList.value = props.tableList;
  nextTick(() => {
    tableRef.value.initTable();
  });
}
// 当某一行被双击时会触发该事件
function cellDblclick(row, column, cell, event) {
  emits('cellDblclick', row, column, cell, event);
}
// 当某一行被双击时会触发该事件
function rowClick(row, column, event) {
  emits('rowClick', row, column, event);
}
// 当某一列的表头被鼠标右键点击时触发该事件
function handleSelectionChange(val, row) {
  emits('handleSelectionChange', val, row);
}
// 当选择行发生变化时会触发该事件
function handleCurrentRowChange(currentRow, oldCurrentRow) {
  emits('handleCurrentRowChange', currentRow, oldCurrentRow);
}
// 当某个单元格被鼠标右键点击时会触发该事件
function handleCellContextmenu(row, column, cell, event) {
  emits('handleCellContextmenu', row, column, cell, event);
}
// 当某一列的表头被鼠标右键点击时触发该事件
function handleHeaderContextmenu(column, event) {
  emits('handleHeaderContextmenu', column, event);
}
// 单选
function handleSingleSelect(row) {
  emits('handleSingleSelect', row);
}
// 多选
function handleSelect(selection, row) {
  emits('handleSelect', selection, row);
}
// 全选
function handleSelectAll(selection) {
  emits('handleSelectAll', selection);
}

defineExpose({
  tableRef,
  tableLoading,
  total,
  tableData,
  countNumMap,
  searchParams, // 请求参数
  initTable, // 初始table list
  getDataList, // 请求列表
  resetPageNum, // pageNum置为1，请求列表
  setTableInfo, // 自定义设置tabledata 、 total、等
});
</script>
<style lang="scss" scoped>
.table_page {
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  .table_page_pagination {
    margin-top: 8px;
  }
}
</style>
